#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
流式TTS WebSocket事件处理器
处理文字转语音相关的WebSocket事件
"""

import asyncio
import base64
import threading
import time
from flask import request
from flask_socketio import emit
from core import extensions
from services.streaming_tts_service import StreamingTTSService


def register_tts_events(socketio):
    """
    注册流式TTS相关事件
    
    Args:
        socketio: SocketIO实例
    """
    
    @socketio.on('start_streaming_tts')
    def handle_start_streaming_tts(data):
        """开始流式TTS合成"""
        client_id = request.sid
        text = data.get('text', '')
        
        if not text:
            emit('tts_error', {
                'type': 'error',
                'message': '文本不能为空',
                'timestamp': int(time.time() * 1000)
            })
            return
        
        # 🔍 文本长度检查和截断（防止TTS服务超长错误）
        MAX_TTS_LENGTH = 300  # TTS最大字符数限制
        original_length = len(text)
        
        if original_length > MAX_TTS_LENGTH:
            # 智能截断：优先在句子结束处截断
            truncate_pos = MAX_TTS_LENGTH
            sentence_endings = ['。', '！', '？', '.', '!', '?', '\n']
            
            # 在最大长度前查找最后一个句子结束符
            for i in range(MAX_TTS_LENGTH - 1, int(MAX_TTS_LENGTH * 0.7), -1):
                if i < len(text) and text[i] in sentence_endings:
                    truncate_pos = i + 1
                    break
            
            text = text[:truncate_pos]
            print(f"⚠️ [TTS] 文本过长 ({original_length}字符)，已截断为 {len(text)} 字符")
            
            # 通知前端文本已被截断
            emit('tts_warning', {
                'type': 'warning',
                'message': f'文本过长已截断: {original_length} → {len(text)} 字符',
                'original_length': original_length,
                'truncated_length': len(text),
                'timestamp': int(time.time() * 1000)
            })
        
        print(f"🎙️ 客户端 {client_id} 请求TTS合成: {text[:50]}...")
        
        try:
            # 如果已有会话，先清理
            if client_id in extensions.tts_sessions:
                print(f"⚠️ 客户端 {client_id} 已有TTS会话，先清理")
                handle_stop_streaming_tts()
            
            # 获取可选参数
            voice_type = data.get('voice_type', 'BV009_streaming')
            encoding = data.get('encoding', 'mp3')
            speed_ratio = data.get('speed_ratio', 1.0)
            volume_ratio = data.get('volume_ratio', 1.0)
            pitch_ratio = data.get('pitch_ratio', 1.0)
            
            # 创建新的事件循环（在单独的线程中）
            def run_tts_loop(client_id, text, voice_type, encoding, speed_ratio, volume_ratio, pitch_ratio):
                loop = asyncio.new_event_loop()
                asyncio.set_event_loop(loop)
                
                # 创建TTS服务实例
                tts_service = StreamingTTSService(
                    appid="1871057448",
                    token="tnph6TBEuRv4MWgh425-XUf6K7AcS2_5",
                    cluster="volcano_tts",
                    voice_type=voice_type,
                    encoding=encoding,
                    speed_ratio=speed_ratio,
                    volume_ratio=volume_ratio,
                    pitch_ratio=pitch_ratio
                )
                
                # 音频块计数器
                audio_chunk_counter = {'count': 0, 'total_size': 0}
                
                # 定义回调函数
                async def on_audio_data_callback(data):
                    """音频数据回调"""
                    try:
                        audio_chunk_counter['count'] += 1
                        audio_chunk_counter['total_size'] += len(data['audio_data'])
                        
                        # 将音频数据编码为base64
                        audio_base64 = base64.b64encode(data['audio_data']).decode('utf-8')
                        
                        # 发送到前端
                        socketio.emit('streaming_tts_audio_chunk', {
                            'type': 'audio_chunk',
                            'audio_data': audio_base64,
                            'encoding': encoding,
                            'sequence_number': data.get('sequence_number'),
                            'is_last': data['is_last'],
                            'chunk_index': audio_chunk_counter['count'],
                            'chunk_size': len(data['audio_data']),
                            'total_size': audio_chunk_counter['total_size'],
                            'timestamp': int(time.time() * 1000)
                        }, room=client_id)
                        
                        print(f"📦 发送音频块 {audio_chunk_counter['count']}, 大小: {len(data['audio_data'])} 字节, is_last: {data['is_last']}")
                        
                    except Exception as e:
                        print(f"❌ 音频数据回调异常: {e}")
                        import traceback
                        traceback.print_exc()
                
                async def on_complete_callback(data):
                    """合成完成回调"""
                    try:
                        print(f"✅ TTS合成完成 - 总块数: {data['total_chunks']}, 总大小: {data['total_size']} 字节")
                        
                        socketio.emit('streaming_tts_complete', {
                            'type': 'complete',
                            'message': 'TTS合成完成',
                            'total_chunks': data['total_chunks'],
                            'total_size': data['total_size'],
                            'timestamp': int(time.time() * 1000)
                        }, room=client_id)
                        
                    except Exception as e:
                        print(f"❌ 完成回调异常: {e}")
                
                def on_error_callback(error_msg):
                    """错误回调"""
                    try:
                        print(f"❌ TTS错误: {error_msg}")
                        
                        socketio.emit('streaming_tts_error', {
                            'type': 'error',
                            'message': error_msg,
                            'timestamp': int(time.time() * 1000)
                        }, room=client_id)
                        
                    except Exception as e:
                        print(f"❌ 错误回调异常: {e}")
                
                # 设置回调
                tts_service.on_audio_data = on_audio_data_callback
                tts_service.on_complete = on_complete_callback
                tts_service.on_error = on_error_callback
                
                # 执行TTS合成
                async def run_synthesis():
                    try:
                        # 连接并合成
                        if await tts_service.connect():
                            await tts_service.synthesize_text(text)
                        else:
                            socketio.emit('streaming_tts_error', {
                                'type': 'error',
                                'message': 'TTS连接失败',
                                'timestamp': int(time.time() * 1000)
                            }, room=client_id)
                    except Exception as e:
                        print(f"❌ TTS合成异常: {e}")
                        import traceback
                        traceback.print_exc()
                        socketio.emit('streaming_tts_error', {
                            'type': 'error',
                            'message': f'合成失败: {str(e)}',
                            'timestamp': int(time.time() * 1000)
                        }, room=client_id)
                    finally:
                        await tts_service.disconnect()
                        
                        # 清理会话
                        if client_id in extensions.tts_sessions:
                            del extensions.tts_sessions[client_id]
                            print(f"🧹 清理TTS会话: {client_id}")
                
                try:
                    # 运行合成任务
                    task = loop.create_task(run_synthesis())
                    
                    # 保存会话信息
                    extensions.tts_sessions[client_id] = {
                        'tts_service': tts_service,
                        'loop': loop,
                        'task': task
                    }
                    
                    # 运行事件循环
                    loop.run_until_complete(task)
                    
                except Exception as e:
                    print(f"❌ TTS循环异常: {e}")
                    import traceback
                    traceback.print_exc()
                finally:
                    loop.close()
            
            # 在独立线程中启动TTS
            tts_thread = threading.Thread(
                target=run_tts_loop,
                args=(client_id, text, voice_type, encoding, speed_ratio, volume_ratio, pitch_ratio),
                daemon=True
            )
            tts_thread.start()
            
            # 发送启动确认
            emit('tts_started', {
                'type': 'started',
                'message': 'TTS合成已启动',
                'text': text,
                'voice_type': voice_type,
                'encoding': encoding,
                'timestamp': int(time.time() * 1000)
            })
            
            print(f"✅ TTS会话已启动: {client_id}")
            
        except Exception as e:
            print(f"❌ 启动TTS失败: {e}")
            import traceback
            traceback.print_exc()
            emit('streaming_tts_error', {
                'type': 'error',
                'message': f'启动失败: {str(e)}',
                'timestamp': int(time.time() * 1000)
            })
    
    @socketio.on('stop_streaming_tts')
    def handle_stop_streaming_tts(data=None):
        """停止流式TTS合成"""
        client_id = request.sid
        print(f"🛑 客户端 {client_id} 请求停止TTS")
        
        try:
            if client_id in extensions.tts_sessions:
                session = extensions.tts_sessions[client_id]
                tts_service = session.get('tts_service')
                loop = session.get('loop')
                
                # 取消任务
                if 'task' in session and session['task']:
                    try:
                        session['task'].cancel()
                        print(f"   ✅ 已取消TTS任务")
                    except Exception as cancel_error:
                        print(f"   ⚠️ 取消任务失败: {cancel_error}")
                
                if tts_service and loop and not loop.is_closed():
                    try:
                        # 断开TTS连接
                        asyncio.run_coroutine_threadsafe(
                            tts_service.disconnect(),
                            loop
                        ).result(timeout=2.0)
                        
                        print(f"   ✅ TTS连接已断开")
                        
                    except Exception as disconnect_error:
                        print(f"   ⚠️ 断开TTS连接失败: {disconnect_error}")
                
                # 清理会话
                del extensions.tts_sessions[client_id]
                print(f"✅ 客户端 {client_id} TTS会话已完全清理")
            else:
                print(f"⚠️ 客户端 {client_id} 没有活跃的TTS会话")
            
            emit('tts_stopped', {
                'type': 'stopped',
                'message': 'TTS合成已停止',
                'timestamp': int(time.time() * 1000)
            })
            
        except Exception as e:
            print(f"❌ 停止TTS失败: {e}")
            import traceback
            traceback.print_exc()
            
            # 即使出错也要尝试清理资源
            try:
                if client_id in extensions.tts_sessions:
                    del extensions.tts_sessions[client_id]
            except:
                pass
            
            emit('tts_error', {
                'type': 'error',
                'message': f'停止失败: {str(e)}',
                'timestamp': int(time.time() * 1000)
            })


def auto_speak_result(client_id, text, voice_type='BV009_streaming', speed_ratio=1.2):
    """
    自动语音播报结果（后台异步执行）
    
    Args:
        client_id: 客户端ID
        text: 要播报的文本
        voice_type: 语音类型，默认女声
        speed_ratio: 语速，默认1.2倍速（更快）
    """
    if not text or not text.strip():
        return
    
    print(f"🔊 [自动播报] 准备播报: {text[:50]}...")
    
    # 创建新的线程来执行TTS
    def run_auto_tts():
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        
        try:
            # 创建TTS服务实例
            tts_service = StreamingTTSService(
                appid="1871057448",
                token="tnph6TBEuRv4MWgh425-XUf6K7AcS2_5",
                cluster="volcano_tts",
                voice_type=voice_type,
                encoding="mp3",
                speed_ratio=speed_ratio,
                volume_ratio=1.0,
                pitch_ratio=1.0
            )
            
            # 收集所有音频块
            audio_chunks = []
            chunk_count = [0]  # 使用列表来在闭包中修改
            
            # 定义回调函数
            async def on_audio_data_callback(data):
                """音频数据回调"""
                try:
                    chunk_count[0] += 1
                    audio_chunks.append(data['audio_data'])
                    
                    # 将音频数据编码为base64
                    audio_base64 = base64.b64encode(data['audio_data']).decode('utf-8')
                    
                    # 发送到前端（使用特殊事件名表示自动播报）
                    extensions.socketio.emit('auto_tts_audio_chunk', {
                        'type': 'auto_audio_chunk',
                        'audio_data': audio_base64,
                        'encoding': 'mp3',
                        'is_last': data['is_last'],
                        'chunk_index': chunk_count[0],
                        'text': text[:100],  # 发送文本片段用于显示
                        'timestamp': int(time.time() * 1000)
                    }, room=client_id)
                    
                    if chunk_count[0] == 1:
                        print(f"🎵 [自动播报] 开始推送音频...")
                    
                except Exception as e:
                    print(f"❌ [自动播报] 音频回调异常: {e}")
            
            async def on_complete_callback(data):
                """合成完成回调"""
                try:
                    print(f"✅ [自动播报] 合成完成 - {chunk_count[0]} 个音频块")
                    
                    # 发送完成信号
                    extensions.socketio.emit('auto_tts_complete', {
                        'type': 'auto_tts_complete',
                        'message': '语音播报完成',
                        'total_chunks': chunk_count[0],
                        'text': text,
                        'timestamp': int(time.time() * 1000)
                    }, room=client_id)
                    
                except Exception as e:
                    print(f"❌ [自动播报] 完成回调异常: {e}")
            
            def on_error_callback(error_msg):
                """错误回调"""
                try:
                    print(f"❌ [自动播报] TTS错误: {error_msg}")
                    
                    extensions.socketio.emit('auto_tts_error', {
                        'type': 'auto_tts_error',
                        'message': error_msg,
                        'timestamp': int(time.time() * 1000)
                    }, room=client_id)
                    
                except Exception as e:
                    print(f"❌ [自动播报] 错误回调异常: {e}")
            
            # 设置回调
            tts_service.on_audio_data = on_audio_data_callback
            tts_service.on_complete = on_complete_callback
            tts_service.on_error = on_error_callback
            
            # 执行TTS合成
            async def run_synthesis():
                try:
                    if await tts_service.connect():
                        await tts_service.synthesize_text(text)
                    else:
                        print(f"❌ [自动播报] TTS连接失败")
                except Exception as e:
                    print(f"❌ [自动播报] TTS合成异常: {e}")
                finally:
                    await tts_service.disconnect()
            
            # 运行合成任务
            loop.run_until_complete(run_synthesis())
            
        except Exception as e:
            print(f"❌ [自动播报] 异常: {e}")
            import traceback
            traceback.print_exc()
        finally:
            loop.close()
    
    # 在独立线程中启动TTS（不阻塞主线程）
    tts_thread = threading.Thread(target=run_auto_tts, daemon=True)
    tts_thread.start()


def convert_audio_to_pcm(audio_bytes):
    """
    将音频数据转换为PCM格式
    
    注意：此函数已不再使用，因为前端现在直接发送PCM数据
    保留此函数仅用于参考或备用方案
    """
    # 前端现在使用AudioContext直接采集PCM数据
    # 不再需要后端转换
    return audio_bytes

